package gobelinmaker.data;

import ij.ImagePlus;
import java.awt.Color;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.LinkedList;

/**
 * Lyukak keresésének az eredményének osztálya.
 *
 * @author imruf84
 */
public class HoleFinderResult {

    /**
     * Eredeti kép.
     */
    private final BufferedImage originalImage;
    /**
     * Végeredmény kép.
     */
    private final BufferedImage resultImage;
    /**
     * Felismert pontok.
     */
    private final Point2D[] pointsFound;
    /**
     * Kiszámolt pontok.
     */
    private final Point2D[][] pointsCalculated;
    private final HashMap<String, LinkedList<Line2D>> lines;

    /**
     * Konstruktor.
     *
     * @param oimage eredeti kép
     * @param rimage végeredmény kép
     * @param pfound felismert pontok
     * @param pcalced kiszámított pontok
     * @param lines vonalak
     */
    public HoleFinderResult(
            BufferedImage oimage,
            BufferedImage rimage,
            Point2D pfound[],
            Point2D pcalced[][],
            HashMap<String, LinkedList<Line2D>> lines) {

        this.originalImage = oimage;
        this.resultImage = rimage;
        this.pointsFound = pfound;
        this.pointsCalculated = pcalced;
        this.lines = lines;
    }

    /**
     * Komponensek kirajzolása képre.
     *
     * @param image kép
     * @param pointsFoundColor talált pontok
     * @param pointsCalculatedColor kiszámított pontok
     * @param linesColor vonalak színei
     * @param needlePoint tű helye
     * @param needlePointColor tű helyének a színe
     * @param cameraPoints kamera kalibrációs pontjai
     * @param cameraPointsColor kamera kalibrációs pontjainak a színe
     * @return kép a kirajzolt komponensekkel
     */
    public BufferedImage drawComponents(
            BufferedImage image,
            Color pointsFoundColor,
            Color pointsCalculatedColor,
            Color linesColor,
            Point2D needlePoint,
            Color needlePointColor,
            Point2D cameraPoints[],
            Color cameraPointsColor) {

        ImagePlus ip = new ImagePlus();
        ip.setImage(image);

        // Vonalak kirajzolása, ha szükséges.
        if (null != linesColor) {
            ip.getProcessor().setColor(linesColor);
            for (LinkedList<Line2D> ll : lines.values()) {
                for (Line2D l : ll) {
                    if (null == l) {
                        continue;
                    }

                    int x1 = (int) (l.getP1().getX() * ((double) image.getWidth() / (double) originalImage.getWidth()));
                    int y1 = (int) (l.getP1().getY() * ((double) image.getHeight() / (double) originalImage.getHeight()));
                    int x2 = (int) (l.getP2().getX() * ((double) image.getWidth() / (double) originalImage.getWidth()));
                    int y2 = (int) (l.getP2().getY() * ((double) image.getHeight() / (double) originalImage.getHeight()));
                    ip.getProcessor().drawLine(x1, y1, x2, y2);
                }
            }
        }

        // Megtalált pontok kirajzolása, ha szükséges.
        if (null != pointsFoundColor) {
            int ps = 6;
            ip.getProcessor().setColor(pointsFoundColor);
            for (Point2D p : pointsFound) {
                if (null == p) {
                    continue;
                }

                int x = (int) (p.getX() * ((double) image.getWidth() / (double) originalImage.getWidth()));
                int y = (int) (p.getY() * ((double) image.getHeight() / (double) originalImage.getHeight()));
                ip.getProcessor().drawLine(x - ps, y, x + ps, y);
                ip.getProcessor().drawLine(x, y - ps, x, y + ps);
            }
        }

        // Kiszámolt pontok kirajzolása, ha szükséges.
        if (null != pointsCalculatedColor) {
            int ps = 6;
            ip.getProcessor().setColor(pointsCalculatedColor);
            for (Point2D pp[] : pointsCalculated) {
                for (Point2D p : pp) {
                    if (null == p) {
                        continue;
                    }

                    int x = (int) (p.getX() * ((double) image.getWidth() / (double) originalImage.getWidth()));
                    int y = (int) (p.getY() * ((double) image.getHeight() / (double) originalImage.getHeight()));
                    ip.getProcessor().drawRect(x - ps, y - ps, ps * 2, ps * 2);
                }
            }
        }

        // Tű helye.
        if (null != needlePointColor) {
            int ps = 10;

            int x = (int) ((needlePoint.getX() * (double) image.getWidth()) - (double) ps / 2);
            int y = (int) ((needlePoint.getY() * (double) image.getHeight()) - (double) ps / 2);

            ip.getProcessor().setColor(needlePointColor);
            ip.getProcessor().drawOval(x, y, ps, ps);
        }

        // Kamera pontjai.
        if (null != cameraPointsColor) {
            int ps = 10;

            int i = 0;
            for (Point2D cameraPoint : cameraPoints) {
                int x = (int) ((cameraPoint.getX() * (double) image.getWidth()) - (double) ps / 2);
                int y = (int) ((cameraPoint.getY() * (double) image.getHeight()) - (double) ps / 2);
                ip.getProcessor().setColor(cameraPointsColor);
                ip.getProcessor().drawOval(x, y, ps, ps);
                ip.getProcessor().drawString(i + "", x, y);
                i++;
            }
        }

        return ip.getBufferedImage();

    }

    /**
     * Eredeti kép lekérdezése.
     *
     * @return kép
     */
    public BufferedImage getOriginalImage() {
        return this.originalImage;
    }

    /**
     * Eredmény kép lekérdezése.
     *
     * @return kép
     */
    public BufferedImage getResultImage() {
        return this.resultImage;
    }

    /**
     * Felismert pontok lekérdezése.
     *
     * @return felismert pontok
     */
    public Point2D[] getPointsFound() {
        return this.pointsFound;
    }

    /**
     * Kiszámított pontok lekérdezése.
     *
     * @return kiszámított pontok
     */
    public Point2D[][] getCalculatedPoints() {
        return this.pointsCalculated;
    }
}
